package com.spring.shiro.service;

import com.spring.shiro.entity.User;
import com.spring.shiro.entity.UserRole;
import com.spring.shiro.entity.UserWithRole;
import com.spring.shiro.mapper.UserMapper;
import com.spring.shiro.mapper.UserRoleMapper;
import com.spring.shiro.qo.QueryRequest;
import com.spring.shiro.utils.MD5Utils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private UserRoleService userRoleService;

    public User findByName(String userName) {
        User user = new User();
        user.setUsername(userName);

        User userOne = userMapper.selectOne(user);

        return userOne;
    }

    @Transactional
    public void registUser(User user) {

        user.setCrateTime(new Date());
        user.setTheme(User.DEFAULT_THEME);
        user.setAvatar(User.DEFAULT_AVATAR);
        user.setSsex(User.SEX_UNKNOW);
        user.setPassword(MD5Utils.encrypt(user.getUsername(), user.getPassword()));
        userMapper.insert(user);

        UserRole ur = new UserRole();
        ur.setUserId(user.getUserId());
        ur.setRoleId(3L);
        this.userRoleMapper.insert(ur);

    }

    @Transactional
    public void updateLoginTime(String userName) {

        Example example = new Example(User.class);
        example.createCriteria().andCondition("lower(username)=", userName.toLowerCase());
        User user = new User();
        user.setLastLoginTime(new Date());
        this.userMapper.updateByExampleSelective(user, example);

    }

    public List<User> findUserWithDept(User user, QueryRequest request) {

        List<User> userList = userMapper.findUserWithDept(user);

        return userList;
    }

    @Transactional
    public void deleteUsers(String ids) {
        //根据userId删除用户
        List<String> list = Arrays.asList(ids.split(","));
        Example example = new Example(User.class);
        example.createCriteria().andIn("userId", list);
        userMapper.deleteByExample(example);

        //删除user_role中间表中的数据
        userRoleService.deleteUserRolesByUserId(ids);

    }

    public User findById(Long userId) {

        //userwithrole继承了user，等于user中加了角色id
        List<UserWithRole> list = this.userMapper.findUserWithRole(userId);

        List<Long> roleList = list.stream().map(e -> e.getRoleId()).collect(Collectors.toList());
        if (null == roleList) return null;

        UserWithRole userWithRole = list.get(0);
        userWithRole.setRoleIds(roleList);

        return userWithRole;
    }

    @Transactional
    public void addUser(User user, Long[] roles) {
        user.setCrateTime(new Date());
        user.setTheme(User.DEFAULT_THEME);
        user.setAvatar(User.DEFAULT_AVATAR);
        user.setPassword(MD5Utils.encrypt(user.getPassword()));
        userMapper.insert(user);

        //插入用户权限表
        setUserRoles(user,roles);
    }

    @Transactional
    public void updateUser(User user, Long[] roles) {
        //修改用户信息
        user.setPassword(null);
        user.setUsername(null);
        user.setModifyTime(new Date());
        userMapper.updateByPrimaryKeySelective(user);

        //删除用户角色中间表信息
        Example example = new Example(UserRole.class);
        example.createCriteria().andCondition("user_id=",user.getUserId());
        userRoleMapper.deleteByExample(example);

        //重新插入用户角色中间表
        setUserRoles(user,roles);
    }

    //公共方法：保存用户的角色
    private void setUserRoles(User user, Long[] roles) {
        Arrays.stream(roles).forEach(roleId -> {
            UserRole ur = new UserRole();
            ur.setUserId(user.getUserId());
            ur.setRoleId(roleId);
            this.userRoleMapper.insert(ur);
        });
    }

    @Transactional
    public void updatePassword(String newPassword) {

        User user = (User) SecurityUtils.getSubject().getPrincipal();

        Example example = new Example(User.class);
        example.createCriteria().andCondition("username=",user.getUsername());

        user.setPassword(MD5Utils.encrypt(user.getUsername().toLowerCase(), newPassword));

        userMapper.updateByExampleSelective(user,example);

    }
}
